package db;

import java.lang.Integer;
import javax.swing.table.*;
import java.sql.*;
import java.util.*;

/** an immutable table model built from getting 
metadata about a table in a jdbc database 
 */
public class JDBCTableModel extends AbstractTableModel {

    Object[][] contents;
    String[] columnNames;
    Class[] columnClasses;

    public JDBCTableModel(Connection conn, String query) throws SQLException {
        super();
        getTableContents(conn, query);
    }

    protected void getTableContents(Connection conn, String query) throws SQLException {

        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery(query);
        ResultSetMetaData rsmd = rs.getMetaData();
        
        ArrayList<String> colNamesList = new ArrayList<String>();
        ArrayList<Class> colClassesList = new ArrayList<Class>();
        
        for(int i=1;rsmd.getColumnCount() >= i;i++) {
            colNamesList.add(rsmd.getColumnLabel(i));
            System.out.println("name: " + rsmd.getColumnLabel(i));
            int dbType = rsmd.getColumnType(i);
            switch (dbType) {
                case Types.INTEGER:
                    colClassesList.add(Integer.class);
                    break;
                case Types.FLOAT:
                    colClassesList.add(Float.class);
                    break;
                case Types.DOUBLE:
                case Types.REAL:
                    colClassesList.add(Double.class);
                    break;
                case Types.DATE:
                case Types.TIME:
                case Types.TIMESTAMP:
                    colClassesList.add(java.sql.Date.class);
                    break;
                default:
                    colClassesList.add(String.class);
                    break;
            };
            System.out.println("type: " + rsmd.getColumnTypeName(i));
        }
        
        columnNames = new String[colNamesList.size()];
        colNamesList.toArray(columnNames);
        columnClasses = new Class[colClassesList.size()];
        colClassesList.toArray(columnClasses);
        
        ArrayList rowList = new ArrayList();
        
        while (rs.next()) {
            ArrayList cellList = new ArrayList();
            for (int i = 0; i < columnClasses.length; i++) {
                Object cellValue = null;
                if (columnClasses[i] == String.class) {
                    cellValue = rs.getString(columnNames[i]);
                } else if (columnClasses[i] == Integer.class) {
                    cellValue = new Integer(
                            rs.getInt(columnNames[i]));
                } else if (columnClasses[i] == Float.class) {
                    cellValue = new Float(
                            rs.getInt(columnNames[i]));
                } else if (columnClasses[i] == Double.class) {
                    cellValue = new Double(
                            rs.getDouble(columnNames[i]));
                } else if (columnClasses[i] == java.sql.Date.class) {
                    cellValue = rs.getDate(columnNames[i]);
                } else {
                    System.out.println("Can't assign " + columnNames[i]);
                }
                cellList.add(cellValue);
            }// for
            Object[] cells = cellList.toArray();
            rowList.add(cells);

        } // while
        // finally create contents two-dim array
        contents = new Object[rowList.size()][];
        for (int i = 0; i < contents.length; i++) {
            contents[i] = (Object[]) rowList.get(i);
        }
        System.out.println("Created model with "
                + contents.length + " rows");

        // close stuff
        rs.close();
        stmt.close();        
    }
    // AbstractTableModel methods

    public int getRowCount() {
        return contents.length;
    }

    public int getColumnCount() {
        if (contents.length == 0) {
            return 0;
        } else {
            return contents[0].length;
        }
    }

    public Object getValueAt(int row, int column) {
        return contents[row][column];
    }

    // overrides methods for which AbstractTableModel
    // has trivial implementations
    public Class getColumnClass(int col) {
        return columnClasses[col];
    }

    public String getColumnName(int col) {
        return columnNames[col];
    }
}